using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace UserManagement.Dal
{
    public interface IRepository
    {
        /// <summary>
        /// Grab all item in a ItemRepository
        /// </summary>
        /// <typeparam name="T">The item type we want to find</typeparam>
        /// <returns>The List of items found in parent</returns>
        IQueryable<T> FindAllEntities<T>();

        /// <summary>
        /// Gets the list of entities that match criteria.
        /// </summary>
        /// <typeparam name="T">type of the entity</typeparam>
        /// <param name="query">The query to search the data source.</param>
        /// <returns>
        /// The list of entity that match the criteria
        /// </returns>
        IQueryable<T> FindEntities<T>(Expression<Func<T, bool>> query) where T : class;

        /// <summary>
        /// Finds the entity by its primary key.
        /// </summary>
        /// <typeparam name="T">Type of the entity</typeparam>
        /// <param name="primaryKey">The primary key of the entity.</param>
        /// <returns>Entity found by database, if system cannot find the entity return null</returns>
        T FindEntityById<T>(object primaryKey);

        /// <summary>
        /// Get a set of information string of certain type of entity
        /// </summary>
        /// <typeparam name="T">The type of entity</typeparam>
        /// <returns>
        /// The list of the entity information class
        /// </returns>
        IEnumerable<IEntityInfo> GetEntityInfos<T>();

        /// <summary>
        /// Adds the entity to data source.
        /// </summary>
        /// <typeparam name="T">The type of entity</typeparam>
        /// <param name="entity">the entity which will be added</param>
        /// <returns></returns>
        T Add<T>(T entity) where T : class;

        /// <summary>
        /// Updates the specified entity of data source.
        /// </summary>
        /// <typeparam name="T">The type of entity</typeparam>
        /// <param name="entity">The entity which will be updated.</param>
        /// <returns></returns>
        T Update<T>(T entity) where T : class;

        /// <summary>
        /// Deletes the specified entity from data source.
        /// </summary>
        /// <typeparam name="T">The type of entity</typeparam>
        /// <param name="entity">The entity which will be removed.</param>
        void Delete<T>(T entity) where T : class;

        /// <summary>
        /// Registers the data change observe to connect repository to data source.
        /// </summary>
        /// <param name="changeHandler">The change handler.</param>
        void RegisterDataChangeObserve(EventHandler changeHandler);

        /// <summary>
        /// Retrieve data again from data source. client need this after data source get changed
        /// </summary>
        /// <typeparam name="T">Type of entity</typeparam>
        /// <param name="entity">The entity need to be refreshed</param>
        void Refresh<T>(ref T entity);
    }
}